package com.example.infowall02.utils;

import com.example.infowall02.mapper.UserMapper;
import jakarta.annotation.Resource;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;

import java.io.IOException;

@Slf4j
//本拦截器只服务于user模块
@WebFilter(filterName = "UserLoginFilter", urlPatterns = {"/user/*"})
public class UserLoginFilter implements Filter {

    private static final String EXCLUDE_ROUTE_1 = "/user/login";
    private static final String EXCLUDE_ROUTE_2 = "/user/logout";
    private static final String EXCLUDE_ROUTE_3 = "/user/register";
//    private static final String EXCLUDE_ROUTE_4 = "/user/getUserInfo";

    @Resource
    private UserMapper userMapper;
    private static final String COOKIE_USERTOKEN_KEY = "cookie_userToken";

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {log.info("调用了 Init 方法");}

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpSession session = request.getSession(false);

        // 获取当前请求的路径
        String requestPath = ((HttpServletRequest) servletRequest).getRequestURI();

        // 判断当前请求路径是否为要排除的特定路由
        if (EXCLUDE_ROUTE_1.equals(requestPath) || EXCLUDE_ROUTE_2.equals(requestPath)|| EXCLUDE_ROUTE_3.equals(requestPath)) {
            // 如果是要排除的路由，直接放行请求，让请求继续向下传递
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        if (session!= null && session.getAttribute("loggedInUser")!= null) {
            log.info("已登录，直接继续处理请求");
            filterChain.doFilter(request, response);
        } else {
            log.info("未登录，检查是否有自动登录的 Cookie");
            Cookie[] cookies = request.getCookies();
            // 检查是否有自动登录的 Cookie
            if (cookies!= null) {
                log.info("存在自动登录的 Cookie");
                for (Cookie cookie : cookies) {
                    if (COOKIE_USERTOKEN_KEY.equals(cookie.getName())) {
                        // 从 Cookie 中获取用户令牌
                        String userTokenFromCookie = cookie.getValue();
                        String usernameFromToken = getUserUsernameFromToken(userTokenFromCookie);
                        if (usernameFromToken!= null) {
                            boolean isUserValid = validateUserFromDatabase(userTokenFromCookie);
                            if (isUserValid) {
                                session = request.getSession();
                                session.setAttribute("loggedInUser", usernameFromToken);
                                session.setAttribute("loggedInUserID", userMapper.getUserByUsername(usernameFromToken).getId());
                                filterChain.doFilter(request, response);
                                return;
                            }
                        }
                    }
                }
            }
            response.sendRedirect("/user/login");
        }
    }
    // 从长令牌中获取用户名
    private String getUserUsernameFromToken(String userToken) {
        try {
            return TokenUtils.getUsernameFromLongToken(userToken);
        } catch (Exception e) {
            log.error("从长令牌获取用户名失败", e);
            return null;
        }
    }
    // 从数据库中验证用户
    private boolean validateUserFromDatabase(String userToken) {
        try {
            String username = getUserUsernameFromToken(userToken);
            if (username!= null) {
                return TokenUtils.validateLongToken(userToken, username) && userMapper.existsByUsername(username);
            }
            return false;
        } catch (Exception e) {
            log.error("数据库查询用户信息失败", e);
            return false;
        }
    }
    @Override
    public void destroy() {
        log.info("调用了 Destroy 方法");
    }
}
